package whu.cn.whushare.net;

import android.content.Context;
import android.text.TextUtils;

import com.android.volley.AuthFailureError;
import com.android.volley.NetworkResponse;
import com.android.volley.ParseError;
import com.android.volley.Response;
import com.android.volley.VolleyError;
import com.android.volley.plus.RequestPro;
import com.android.volley.toolbox.HttpHeaderParser;
import com.androidplus.util.LogUtils;
import com.google.gson.reflect.TypeToken;

import org.apache.http.protocol.HTTP;

import java.io.UnsupportedEncodingException;
import java.lang.reflect.Type;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.util.HashMap;
import java.util.Map;

import whu.cn.whushare.bean.Result;
import whu.cn.whushare.common.ResultCode;
import whu.cn.whushare.common.UserManager;
import whu.cn.whushare.util.GsonUtil;

/**
 * 类 名：CommonRequest
 * 功 能：定义公共网络请求
 *       包含公共网络请求构造方法以及对网络请求响应的解析方法
 * @param <T>
 */
public class CommonRequest<T> extends RequestPro<Result<T>> {
	public static final String TAG = "CommonRequest";

    protected TypeToken<Result<T>> mTypeToken;
	protected String mUrl;
	private Context mContext;

	private static final String SET_COOKIE_KEY = "Set-Cookie";
	private static final String COOKIE_KEY = "Cookie";
	private static final String SESSION_COOKIE = "sessionid";

    /**
     * 函数名：CommonRequest
     * 功 能：公共网络请求类构造方法，主要设置了网络请求成功和失败时所执行的操作
     * @param context - application context
     * @param method - 网络请求方式
     * @param type - 下载参数解析类型
     * @param params -
     * @param response - 网络响应监听器
     * @param typeToken - gson泛型解析类
     * @param obj -
     */
	public CommonRequest(Context context, int method, final DownloadParams.PARSING_TYPE type,
			Map<String, String> params, final NetResponseListener response, TypeToken<Result<T>> typeToken,
			final Object obj) {
		super(method, type.getUrl(), params, new Response.Listener<Result<T>>() {
			@Override
			public void onResponse(Result<T> t) {
				if (t != null && t.getCode() == ResultCode.SUCCESS.getCode()) {
					response.onSuccess(type, t, obj);
				} else {
					response.onFail(type, t, new VolleyError());
				}
			}
		}, new Response.ErrorListener() {
			@Override
			public void onErrorResponse(VolleyError error) {
				response.onFail(type, new Result<T>(null), error);
			}
		});
		mUrl = type.getUrl();
		mTypeToken = typeToken;

		mContext = context;
	}

	@Override
    /**
     * 解析网络请求错误，当网络请求出错时调用该方法，执行其中的操作
     */
	protected VolleyError parseNetworkError(VolleyError volleyError) {
		LogUtils.e(TAG, "CommonRequest parseNetworkError:" + volleyError.toString());
		if (volleyError.getMessage() != null && volleyError.getMessage().equals("empty"))
			return new VolleyError();

		return super.parseNetworkError(volleyError);
	}

	@Override
    /**
     * 将网络中返回的原生字节内容解析为恰当的response类型
     * @param response - NetworkResponse对象，包含网络响应消息
     */
	protected Response<Result<T>> parseNetworkResponse(NetworkResponse response) {
		try {
            //将response.data按照HttpHeaderParser.parseCharset(response.headers, HTTP.UTF_8)这种编码方式转化为一串字符串
			String jsonString = new String(response.data, HttpHeaderParser.parseCharset(response.headers, HTTP.UTF_8));
			LogUtils.d(TAG, "url :" + mUrl + "\n response:" + jsonString);

			if (TextUtils.isEmpty(jsonString)) {
				return Response.error(new VolleyError("empty"));
			}

            //将jsonString解析为mTypeToken类型后返回该类型对象
			Result<T> result = GsonUtil.getResult(jsonString, mTypeToken);


			if (result == null) {
				return Response.error(new VolleyError("unknown"));
			}
			if (result.getCode() != ResultCode.SUCCESS.getCode()) {
				Response.error(new VolleyError(result.getMsg()));
			}
			return Response.success(result, HttpHeaderParser.parseCacheHeaders(response));
		} catch (UnsupportedEncodingException e) {
			return Response.error(new ParseError(e));
		}
	}

	@Override
    //自定义头文件，设置头文件的cookie值
	public Map<String, String> getHeaders() throws AuthFailureError {
		Map<String, String> header = new HashMap<>();
        String cookieStr = null;
        try {
            cookieStr = DownloadParams.USER_ID + "=" + URLEncoder.encode(UserManager.getInstance(mContext).getCurrentUser().getId(), "UTF-8")
                    + ";" + DownloadParams.USER_PASS + "="
                    + UserManager.getInstance(mContext).getCurrentUser().getPassword();
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        header.put(COOKIE_KEY, cookieStr);
		return header;
	}
}
